using UnityEngine;
using UnityEngine.UI;

public enum SwordType
{
    Regular,
    Bounce,
    Pierce,
    Spin
}

public class SwordSkillController : Skill
{
    public SwordType swordType = SwordType.Regular;
    [Header("Skill info")]
    [SerializeField] private UiSkillTreeSlot swordUnlockButton;
    public bool SwordUnlocked { get; private set; }
    [SerializeField] private GameObject swordPrefab;
    [SerializeField] private Vector2 launchForce;
    [SerializeField] private float swordGravity;
    [SerializeField] private float freezeTimeDuration;
    [SerializeField] private float returnSpeed;
    private Vector2 finalDirection;
    [Header("Aim info")]
    [SerializeField] private int numberOfDots;
    [SerializeField] private float distanceBetweenDots;
    [SerializeField] private GameObject dotPrefab;
    [SerializeField] private Transform dotParent;
    private GameObject[] dots;
    [Header("Bounce info")]
    [SerializeField] private UiSkillTreeSlot bounceUnlockButton;
    [SerializeField] private int bounceCount;
    [SerializeField] private float bounceGravity;
    [SerializeField] private float bounceSpeed;
    [Header("Pierce info")]
    [SerializeField] private UiSkillTreeSlot pierceUnlockButton;
    [SerializeField] private int pierceAmount;
    [SerializeField] private float pierceGravity;
    [Header("Spin info")]
    [SerializeField] private UiSkillTreeSlot spinUnlockButton;
    [SerializeField] private float hitCooldown;
    [SerializeField] private float maxTravelDistance;
    [SerializeField] private float spinDuration;
    [SerializeField] private float spinGravity;
    [Header("Passive skills")]
    [SerializeField] private UiSkillTreeSlot timeStopUnlockButton;
    public bool TimeStopUnlocked { get; private set; }
    [SerializeField] private UiSkillTreeSlot vulnerableUnlockButton;
    public bool VulnerableUnlocked { get; private set; }

    protected override void Start()
    {
        base.Start();
        GenereateDots();
        SetupGravity();
        swordUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockSword);
        bounceUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockBounceSword);
        pierceUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockPierceSword);
        spinUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockSpinSword);
        timeStopUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockTimeStop);
        vulnerableUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockVulnerable);
    }

    protected override void Update()
    {
        base.Update();
        if (Input.GetKeyUp(KeyCode.Mouse1))
        {
            finalDirection = new(AimDirection().x * launchForce.x, AimDirection().y * launchForce.y);
        }

        if (!Input.GetKey(KeyCode.Mouse1))
            return;
        for (int i = 0; i < numberOfDots; i++)
        {
            dots[i].transform.position = DotsPostion(distanceBetweenDots * (i + 1));
        }
    }

    protected override void CheckUnlock()
    {
        UnlockSword();
        UnlockBounceSword();
        UnlockPierceSword();
        UnlockSpinSword();
        UnlockTimeStop();
        UnlockVulnerable();
    }

    private void UnlockTimeStop()
    {
        if (!timeStopUnlockButton.unlocked || TimeStopUnlocked) return;
        TimeStopUnlocked = true;
    }

    private void UnlockVulnerable()
    {
        if (!vulnerableUnlockButton.unlocked || VulnerableUnlocked) return;
        VulnerableUnlocked = true;
    }

    private void UnlockSword()
    {
        if (!swordUnlockButton.unlocked || SwordUnlocked) return;
        swordType = SwordType.Regular;
        SwordUnlocked = true;
    }

    private void UnlockBounceSword()
    {
        if (!bounceUnlockButton.unlocked || swordType == SwordType.Bounce) return;
        swordType = SwordType.Bounce;
    }

    private void UnlockPierceSword()
    {
        if (!pierceUnlockButton.unlocked || swordType == SwordType.Pierce) return;
        swordType = SwordType.Pierce;
    }

    private void UnlockSpinSword()
    {
        if (!spinUnlockButton.unlocked || swordType == SwordType.Spin) return;
        swordType = SwordType.Spin;
    }

    public void CreateSword()
    {
        GameObject newSword = Instantiate(swordPrefab, Player.transform.position, transform.rotation);
        SwordSkill newSwordScript = newSword.GetComponent<SwordSkill>();
        switch (swordType)
        {
            case SwordType.Regular:
                break;
            case SwordType.Bounce:
                swordGravity = bounceGravity;
                newSwordScript.SetupBounce(true, bounceCount, bounceSpeed);
                break;
            case SwordType.Pierce:
                newSwordScript.SetupPierce(pierceAmount);
                break;
            case SwordType.Spin:
                newSwordScript.SetupSpin(true, maxTravelDistance, spinDuration, hitCooldown);
                break;
            default:
                break;
        }

        newSwordScript.SetupSword(finalDirection, swordGravity, Player, freezeTimeDuration, returnSpeed);
        Player.AssignNewSword(newSword);
        DotsActive(false);
    }

    private void SetupGravity()
    {
        switch (swordType)
        {
            case SwordType.Regular:
                break;
            case SwordType.Bounce:
                swordGravity = bounceGravity;
                break;
            case SwordType.Pierce:
                swordGravity = pierceGravity;
                break;
            case SwordType.Spin:
                swordGravity = spinGravity;
                break;
        }
    }

    #region Aim
    private Vector2 AimDirection()
    {
        Vector2 playerPosition = Player.transform.position;
        if (Camera.main)
        {
            Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            Vector2 direction = mousePosition - playerPosition;
            direction = direction.normalized;
            return direction;
        }
        return default;
    }

    public void DotsActive(bool isActive)
    {
        for (int i = 0; i < numberOfDots; i++)
        {
            dots[i].SetActive(isActive);
        }
    }

    private void GenereateDots()
    {
        dots = new GameObject[numberOfDots];
        for (int i = 0; i < numberOfDots; i++)
        {
            dots[i] = Instantiate(dotPrefab, Player.transform.position, Quaternion.identity, dotParent);
            dots[i].SetActive(false);
        }
    }

    private Vector2 DotsPostion(float t)
    {
        Vector2 position = new Vector2(Player.transform.position.x, Player.transform.position.y) +
                           new Vector2(AimDirection().x * launchForce.x, AimDirection().y * launchForce.y) * t +
                           0.5f * (Physics2D.gravity * swordGravity) * (t * t);
        return position;
    }
    #endregion
}